#include <iostream>
#include <string.h>

#define MEMORYPOOL(T, count) \
void* operator new(size_t size)\
{\
    std::cout<<"重载new"<<std::endl;\
    return MemoryPool<sizeof(T),count>::GlobalInstance()->malloc();\
}\
void operator delete(void *p)\
{\
    std::cout<<"重载delete"<<std::endl;\
    MemoryPool<sizeof(Test),1024>::GlobalInstance()->free(p);\
}\

template<int NodeSize, int NodeCount>
class MemoryPool
{
public:
    static MemoryPool* GlobalInstance()
    {
        static MemoryPool pool;
        return &pool;
    }

    MemoryPool()
    {
        NodeHeader = nullptr;
        BlockHeader = nullptr;
    }
    ~MemoryPool()
    {
        NodeHeader = nullptr;
        while(BlockHeader != nullptr)
        {
            auto ptr = BlockHeader->next;
            delete BlockHeader;
            BlockHeader = ptr;
        }
    }
    void* malloc();
    void free(void *p);

private:
    //小块内存节点
    union FreeNode
    {
        char data[NodeSize];
        FreeNode *next;//嵌入式指针
    };
    
    struct MemBlock
    {
        FreeNode Node[NodeCount];
        MemBlock *next;
    };
    FreeNode* NodeHeader;
    MemBlock* BlockHeader;
};

template<int NodeSize, int NodeCount>
void* MemoryPool<NodeSize, NodeCount>::malloc()
{
    //没有空闲节点:扩容
    if(NodeHeader == nullptr)
    {
        MemBlock *newBlock = new MemBlock;
        //把大内存块的小内存都连接起来
        for(int i = 0; i < NodeCount - 1; i++)//i <= NodeCount - 2
        {
            newBlock->Node[i].next = &newBlock->Node[i + 1];
        }
        newBlock->Node[NodeCount - 1].next = nullptr;

        //头插法
        newBlock->next = BlockHeader;
        BlockHeader = newBlock;

        //把大内存的第一个节点地址给到nodeheader
        NodeHeader = BlockHeader->Node;
    }
    auto ptr = NodeHeader;
    NodeHeader  = NodeHeader->next;
    //清空内存
    memset(ptr, 0, NodeSize);
    return ptr;
}

//单链表头插简单
template<int NodeSize, int NodeCount>
void MemoryPool<NodeSize,NodeCount>::free(void *p)
{
    FreeNode *node = static_cast<FreeNode*> (p);//静态转换
    memset(node, 0, NodeSize);
    //头插法
    node->next = NodeHeader;
    NodeHeader = node;
}